package org.jsets.fastboot.util;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.DecimalFormat;
import java.util.List;
import java.util.concurrent.TimeUnit;

import com.google.common.collect.Lists;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.hardware.GlobalMemory;
import oshi.hardware.HardwareAbstractionLayer;
import oshi.software.os.FileSystem;
import oshi.software.os.OSFileStore;
import oshi.software.os.OperatingSystem;

@Slf4j
public class MachineUtils {

	public static void main(String[] args) {
		getMachineSnapshoot();
	}

	public static Snapshoot getMachineSnapshoot() {
		Snapshoot snapshoot = new Snapshoot();
		SystemInfo systemInfo = new SystemInfo();
		HardwareAbstractionLayer hardware = systemInfo.getHardware();

		
		snapshoot.setOsName(System.getProperty("os.name"));
        snapshoot.setOsArch(System.getProperty("os.arch"));
        snapshoot.setUserDir(System.getProperty("user.dir"));
		try {
			InetAddress address = InetAddress.getLocalHost();
	        snapshoot.setName(address.getHostName());
	        snapshoot.setIp(address.getHostAddress());
		} catch (UnknownHostException e1) {
			// ... ...
		}

		// --------------JVM---------------
		snapshoot.setJdkVersion(System.getProperty("java.version"));
		snapshoot.setJdkHome(System.getProperty("java.home"));
		snapshoot.setJvmMenTotal(new DecimalFormat("#.#").format(Runtime.getRuntime().totalMemory() * 1.0 / 1024 / 1024) + " MB");
		snapshoot.setJvmMenMax(new DecimalFormat("#.#").format(Runtime.getRuntime().maxMemory()* 1.0 / 1024 / 1024) + " MB");
		snapshoot.setJvmMenFree(new DecimalFormat("#.#").format(Runtime.getRuntime().freeMemory()* 1.0 / 1024 / 1024) + " MB");

		// ------------CPUs----------------
		CentralProcessor processor = hardware.getProcessor();
		long[] prevTicks = processor.getSystemCpuLoadTicks();
		try {
			TimeUnit.SECONDS.sleep(1);// 睡眠1s
		} catch (InterruptedException e) {
			// ... ...
		}
		long[] ticks = processor.getSystemCpuLoadTicks();
		long nice = ticks[CentralProcessor.TickType.NICE.getIndex()]
				- prevTicks[CentralProcessor.TickType.NICE.getIndex()];
		long irq = ticks[CentralProcessor.TickType.IRQ.getIndex()]
				- prevTicks[CentralProcessor.TickType.IRQ.getIndex()];
		long softirq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()]
				- prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()];
		long steal = ticks[CentralProcessor.TickType.STEAL.getIndex()]
				- prevTicks[CentralProcessor.TickType.STEAL.getIndex()];
		long cSys = ticks[CentralProcessor.TickType.SYSTEM.getIndex()]
				- prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()];
		long user = ticks[CentralProcessor.TickType.USER.getIndex()]
				- prevTicks[CentralProcessor.TickType.USER.getIndex()];
		long iowait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()]
				- prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()];
		long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()]
				- prevTicks[CentralProcessor.TickType.IDLE.getIndex()];
		long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal;
		snapshoot.setCpuNum(processor.getLogicalProcessorCount());
		snapshoot.setCpuUsageRate(new DecimalFormat("#.##%").format(cSys * 1.0 / totalCpu));
		snapshoot.setCpuUserUsageRate(new DecimalFormat("#.##%").format(user * 1.0 / totalCpu));
		snapshoot.setCpuWaitRate(new DecimalFormat("#.##%").format(iowait * 1.0 / totalCpu));
		snapshoot.setCpuFreeRate(new DecimalFormat("#.##%").format(idle * 1.0 / totalCpu));

		log.info("cpu核数[{}]", snapshoot.getCpuNum());
		log.info("cpu系统使用率[{}]", snapshoot.getCpuUsageRate());
		log.info("cpu用户使用率[{}]", snapshoot.getCpuUserUsageRate());
		log.info("cpu当前等待率[{}]", snapshoot.getCpuWaitRate());
		log.info("cpu当前空闲率[{}]", snapshoot.getCpuFreeRate());

		// ------------Mems----------------
		GlobalMemory memory = hardware.getMemory();
		snapshoot.setMemTotal(new DecimalFormat("#.##").format(memory.getTotal() * 1.0 / 1024 / 1024 / 1024));
		snapshoot.setMemUsed(new DecimalFormat("#.##").format((memory.getTotal() - memory.getAvailable()) * 1.0 / 1024 / 1024 / 1024));
		snapshoot.setMemFree(new DecimalFormat("#.##").format(memory.getAvailable() * 1.0 / 1024 / 1024 / 1024));

		// ------------Disks----------------
		List<Disk> disks = Lists.newArrayList();
		OperatingSystem operatingSystem = systemInfo.getOperatingSystem();
        FileSystem fileSystem = operatingSystem.getFileSystem();
        List<OSFileStore> stores = fileSystem.getFileStores();
        for (OSFileStore store : stores) {
        	Disk disk = new Disk();
            long free = store.getUsableSpace();
            long total = store.getTotalSpace();
            long used = total - free;
            
            disk.setName(store.getName());
            disk.setType(store.getType());
            disk.setTotal(String.format("%.1f GB", (total*1.0)/1024/1024/1024));
            disk.setUsed(String.format("%.1f GB", (used*1.0)/1024/1024/1024));
            disk.setFree(String.format("%.1f GB", (free*1.0)/1024/1024/1024));
            disk.setUsage(new DecimalFormat("#.##").format((used*1.0 / total*1.0)*100));
            disks.add(disk);
        }
        snapshoot.setDisks(disks);

		System.out.println(JsonUtils.toIndentJson(snapshoot));
		return snapshoot;
	}

	@Data
	public static class Disk {
		private String name;// 盘符名称
		private String type;// 文件类型
		private String total;// 总大小
		private String free;// 剩余大小
		private String used;// 已经使用量
		private String usage;// 资源的使用率
	}

	@Data
	public static class Snapshoot {

		private String name;// 服务器名称
		private String ip;// 服务器IP
		private String userDir;// 项目路径
		private String osName;// 操作系统
		private String osArch;// 系统架构

		private int cpuNum;// CPU核心数
		private String cpuUsageRate;// CPU使用率
		private String cpuSysUsageRate;// CPU系统使用率
		private String cpuUserUsageRate;// CPU用户使用率
		private String cpuWaitRate;// CPU当前等待率
		private String cpuFreeRate;// CPU当前空闲率

		private String memTotal;// 内存总量
		private String memUsed;// 内存用量
		private String memFree;// 内存剩余

		private String jdkVersion;// JDK版本
		private String jdkHome;// JDK路径
	    private String jvmMenTotal;//当前JVM占用的内存总数(M)
	    private String jvmMenMax;//JVM最大可用内存总数(M)
	    private String jvmMenFree;//JVM空闲内存(M)

		private List<Disk> disks;// 磁盘
	}

}
